package com.djl.zenithbite.controller.user;

import com.djl.zenithbite.common.constants.VerifyCodeConstants;
import com.djl.zenithbite.common.constants.VerifyCodeHtmlConstants;
import com.djl.zenithbite.common.response.BaseResponse;
import com.djl.zenithbite.dto.request.user.RegisterVerifyCodeRequest;
import com.djl.zenithbite.dto.request.user.UpdateUserInfoRequest;
import com.djl.zenithbite.dto.request.user.UserLoginRequest;
import com.djl.zenithbite.dto.request.user.UserRegisterRequest;
import com.djl.zenithbite.service.EnrollService;
import com.djl.zenithbite.service.user.UserService;
import com.djl.zenithbite.util.MailUtil;
import com.djl.zenithbite.util.RedisKeyUtil;
import com.djl.zenithbite.util.VerifyCodeUtil;
import com.djl.zenithbite.util.check.AssertUtil;
import com.google.code.kaptcha.Producer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/api/user/auth")
public class AuthController {

    private Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private MailUtil mailUtil;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private Producer kaptcha;

    @Value("${server.servlet.context-path}")
    String contextPath;

    @GetMapping("/kaptcha")
    public void getCode(HttpServletResponse response/*, HttpSession session*/) {
        String text = kaptcha.createText();

        String kaptchaTicket = UUID.randomUUID().toString();
        //设置表示验证码的信息
        Cookie cookie = new Cookie("kaptchaTicket", kaptchaTicket);
        cookie.setPath(contextPath);
        cookie.setMaxAge(60);
        response.addCookie(cookie);

        String codeKey = RedisKeyUtil.getCodeKey(kaptchaTicket);
        redisTemplate.opsForValue().set(codeKey, text, 60, TimeUnit.SECONDS);

        // session.setAttribute("code", text);
        BufferedImage image = kaptcha.createImage(text);
        try {
            response.setContentType("image/png");
            OutputStream os = response.getOutputStream();
            //使用工具直接发送将图片输出到指定流
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
            logger.error("验证码错误：" + e.getMessage());
        }
    }

    @PostMapping("/login")
    public BaseResponse login(@RequestBody UserLoginRequest request, HttpSession httpSession, HttpServletResponse response,@CookieValue("kaptchaTicket") String ticket){
       request.setHttpSession(httpSession);
       request.setTicket(ticket);
       request.setResponse(response);
       return userService.login(request);
    }

    @PostMapping("/logout")
    public BaseResponse logout(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        Optional<Cookie> token = Arrays.stream(cookies).filter(cookie -> cookie.getName().equals("token")).findFirst();
        return userService.logout(token.map(Cookie::getValue).orElse(null));
    }

    @PostMapping("/register")
    public BaseResponse register(@RequestBody UserRegisterRequest request, HttpSession httpSession,@CookieValue("emailTicket") String ticket){
        request.setHttpSession(httpSession);
        request.setTicket(ticket);
        return userService.register(request);
    }

    @PostMapping("/sendVerifyCode")
    public BaseResponse sendVerify(@RequestBody RegisterVerifyCodeRequest request, HttpSession session,HttpServletResponse response){
        int generateCode = VerifyCodeUtil.generateCode();

       // session.setAttribute(VerifyCodeConstants.REGISTER_VERIFY_CODE_KEY,generateCode);
        //session.setAttribute(VerifyCodeConstants.REGISTER_VERIFY_DATE_KEY,new Date());
        String codeKey = UUID.randomUUID().toString();
        String codeKey1 = RedisKeyUtil.getCodeKey(codeKey);
        redisTemplate.opsForValue().set(codeKey1,generateCode);
        Cookie cookie = new Cookie("emailTicket", codeKey);
        cookie.setPath(contextPath);
        cookie.setMaxAge(60);
        response.addCookie(cookie);


        mailUtil.send(request.getUserEmail(),"ZenithBite Verify Code",
                VerifyCodeHtmlConstants.MAIL_CONSTANT
                        .replace("{{emailContent}}",String.valueOf(generateCode)));

        return new BaseResponse();
    }

    @PostMapping("/verifyEmailCode")
    public BaseResponse verifyEmailCode(@RequestBody RegisterVerifyCodeRequest request, HttpSession session,@CookieValue("emailTicket") String ticket){

       // boolean b = EnrollService.inspectCheckCodeService(VerifyCodeConstants.REGISTER_VERIFY_CODE_KEY, VerifyCodeConstants.REGISTER_VERIFY_DATE_KEY, request.getVerifyCode(), session);
        String codeKey;
        if (ticket == null) {
            codeKey = null;
        } else {
            codeKey = RedisKeyUtil.getCodeKey(ticket);
        }

        Object codeObj = redisTemplate.opsForValue().get(codeKey);
        String realCode = codeObj != null ? codeObj.toString() : null;
        AssertUtil.isTrue(StringUtils.equals(realCode, request.getVerifyCode()), "verify code error");

        BaseResponse response = new BaseResponse();
        response.setCode(BaseResponse.SUCCESS);

        return response;
    }

    @PostMapping("/resetPassword")
    public BaseResponse resetPassword(@RequestBody UserRegisterRequest request){

        return userService.resetPassword(request);
    }


    @PostMapping("/updateUserInfo")
    public BaseResponse updateUserInfo(@RequestBody UpdateUserInfoRequest request){
        return userService.updateUserInfo(request);
    }
}
